import "../../App.css";
import { useContext } from "react";
import {
  PrimaryButton,
  MessageBar,
  MessageBarType,
  Stack
} from '@fluentui/react';
import { fs, path } from '@tauri-apps/api';
import { camelToKebab, stackTokens, stackStyles, columnProps, tryGetJavaApiFile, getServer2Path, ensureDirectoryExists, copyPackageTools, isIgnoreFolder } from "../utils";
import useNameInput from "../Commons/useNameInput";
import useInstallPath from "../Commons/useInstallPath";
import usePluginInstallPath from "../Commons/usePluginInstallPath";
import { GlobalContext } from "../Context/global";
import usePackageClassInput from "../Commons/usePackageClassInput";
import { RS } from "../../i18n/config";

const API_NAME = 'forguncy-server-api';
const TEMPLATE_FILE_WHITE_LIST: { [key: string]: true } = {
  "pom.xml": true,
  "WEB_API_TEMPLATE.java": true
}
function WebApi() {
  const [nameDom, name, nameValid] = useNameInput({ label: "Web Api", initValue: 'CustomApi' });
  const [forguncyInstallPathDom, forguncyPath, forguncyPathValid, jarVersion, _setForguncyPath] = useInstallPath({
    getDependenceVersion: tryGetJavaApiFile,
    apiName: API_NAME
  })
  const [pluginInstallDom, installPath, installPathValid] = usePluginInstallPath({ label: "Web Api", defaultPath: "forguncy-java-api" });
  const { dispatch } = useContext(GlobalContext);

  const [PackageClassDom, packageClass, packageNameIsValid] = usePackageClassInput();
  const allValid = nameValid && installPathValid && forguncyPathValid && packageNameIsValid;
  const fullInstallPath = `${installPath}${name}`;
  const createJavaWebApi = async () => {
    const sourceCodeInstallPath = await path.join(fullInstallPath, name);
    try {
      await ensureDirectoryExists(sourceCodeInstallPath);
      const packagePath = await path.join(sourceCodeInstallPath, "src", "main", "java", ...packageClass.split('.'));
      await ensureDirectoryExists(packagePath);

      const thePath = await path.join(await path.resourceDir(), "web-api-template");
      await copyJavaWebApiFilesRecursively(thePath, sourceCodeInstallPath, name, jarVersion, forguncyPath, packagePath, packageClass, thePath)
      await copyPackageTools(fullInstallPath);
    } catch (error: any) {
      dispatch?.({ type: 'errorMsg', payload: error.toString() });
      return;
    }
    dispatch?.({ type: 'createSuccess', payload: sourceCodeInstallPath })
  }
  return (
    <div className="container">
      <form noValidate autoComplete="off">
        <Stack horizontal tokens={stackTokens} styles={stackStyles}>
          <Stack {...columnProps}>
            {nameDom}
            {PackageClassDom}
            {forguncyInstallPathDom}
            {pluginInstallDom}
            {(!(allValid)) ? undefined : <MessageBar
              messageBarType={MessageBarType.success}
              isMultiline={true}
            >
              {RS.Project_Will_Be_Created_In}{fullInstallPath}
            </MessageBar>}
          </Stack>
        </Stack>
      </form>
      <div style={{ textAlign: 'center' }}>
        <PrimaryButton onClick={createJavaWebApi} disabled={!(allValid)} style={{ margin: '36px 24px', width: '240px' }}>{RS.Create_Web_Api}</PrimaryButton>
      </div>
    </div>
  );
}

export default WebApi;


async function copyJavaWebApiFilesRecursively(sourcePath: string, targetPath: string, name: string, jarVersion: string, forguncyPath: string, packagePath: string, packageClass: string, root: string) {

  if (!(await fs.exists(sourcePath))) {
    return;
  }

  if (!(await fs.exists(targetPath))) {
    await fs.createDir(targetPath);
  }

  const files = await fs.readDir(sourcePath);

  files.forEach(async (file) => {
    const currentSource = await path.join(sourcePath, file.name || '');
    const currentTarget = await path.join(targetPath, file.name || '');

    const isDir = await getIsDir(currentSource);
    if (isDir) {
      copyJavaWebApiFilesRecursively(currentSource, currentTarget, name, jarVersion, forguncyPath, packagePath, packageClass, root);
    } else {
      if (await isIgnoreFolder(file, root) || !TEMPLATE_FILE_WHITE_LIST[file.name || '']) {
      } else if (file.name === 'WEB_API_TEMPLATE.java') {
        //主类的文件名 CustomApi 主类名 CustomApi
        const uint8Array = await fs.readBinaryFile(currentSource);
        const decoder = new TextDecoder('utf-8');
        const decodedString = decoder.decode(uint8Array);
        const targetString = decodedString.replace(/CUSTOM_API_NAME/g, name).replace(/ORG_EXAMPLE/g, packageClass);
        const newTarget = await path.join(packagePath, name + '.java');
        await fs.writeTextFile(newTarget, targetString);
      } else if (file.name === 'pom.xml') {
        const uint8Array = await fs.readBinaryFile(currentSource);
        const decoder = new TextDecoder('utf-8');
        const decodedString = decoder.decode(uint8Array);
        const jarPath = (await path.join(forguncyPath, await getServer2Path(forguncyPath), 'javaAdapterServerBin')).split("\\").join("/");
        const javaPath = (await path.join(forguncyPath, await getServer2Path(forguncyPath), 'bpmJavaServerBin')).split("\\").join("/");
        const targetString = decodedString.replace(/WEB_API_TEMPLATE/g, camelToKebab(name))
          .replace(/FORGUNCY_SERVER_API_VERSION/g, jarVersion)
          .replace(/PLUGIN_ABS_PATH/g, jarPath)
          .replace(/JAVA_PATH/g, javaPath);
        await fs.writeTextFile(currentTarget, targetString); //  pom 改 artifactId name
      } else {
        await fs.copyFile(currentSource, currentTarget);
      }
    }
  });

  async function getIsDir(currentSource: string) {
    try {
      await fs.readDir(currentSource);
      return true;
    } catch (error) {
      return false;
    }
  }
}